<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Libs\Frame;

use Srv\Apps\Proto\Enum\LangKeyEnum;
use Srv\Libs\Boot;
use Srv\Libs\ConfModel\LangConf;

final class Lang
{
    private static string $defaultLangType              = 'zh';         // 默认语言
    private static string $langType                     = 'zh';         // 当前语言
    private static array $langData                      = [];           // 已加载语言数据
    private static array $langFileList                  = [];           // 所有语言数据文件列表
    private static array $aliasList                     = [             // 别名列表
        'zh-hans'       => 'zh',    // 简体中文
        'zh-hant'       => 'zh',    // 繁体中文
        'zh-cn'         => 'zh',    // 简体中文
        'zh-tw'         => 'zh',    // 繁体中文,台湾
        'zh-hk'         => 'zh',    // 繁体中文,香港
        'zh-mo'         => 'zh',    // 繁体中文,澳门
        'zh-sg'         => 'zh',    // 简体中文,新加坡
        'zh-my'         => 'zh',    // 简体中文,马来西亚
    ];

    /**
     * @param LangConf $LangConf
     * @return bool
     * init
     */
    public static function init(LangConf $LangConf):bool
    {
        $langType                   = self::formatLangType($LangConf->getDefaultSet());
        if(strlen($langType) < 2) return false;
        self::$defaultLangType      = $langType;
        self::$langType             = $langType;
        self::$langData             = [];
        self::$langFileList         = $LangConf->getFiles();
        return true;
    }

    /**
     * @param string $langType
     * @param string $langTypePrefix
     * @return string
     * formatLangType
     */
    public static function formatLangType(string $langType, string &$langTypePrefix = ''):string
    {
        $langTypePrefix = '';
        $langType       = preg_replace('/[^a-z\d]/', '-', strtolower(trim($langType)));
        if(strlen($langType) < 1) return $langType;
        list($langTypePrefix) = explode('-', $langType, 2);
        return $langType;
    }

    /**
     * @return string
     * getDefaultLangType
     */
    public static function getDefaultLangType():string
    {
        return self::$defaultLangType;
    }

    /**
     * @return string
     * getLangType
     */
    public static function getLangType():string
    {
        return self::$langType;
    }

    /**
     * @param string $langType
     * @param bool $isSetDefault
     * @return bool
     * setLangType
     */
    public static function setLangType(string $langType, bool $isSetDefault):bool
    {
        if($isSetDefault) self::$langType = self::$defaultLangType;
        $langTypePrefix     = '';
        $langType           = self::formatLangType($langType, $langTypePrefix);
        if(strlen($langType) < 2) return false;
        if(isset(self::$aliasList[$langType])) $langType = self::$aliasList[$langType];
        if(isset(self::$langFileList[$langType])){
            self::$langType = $langType;
            return true;
        }
        if(isset(self::$langFileList[$langTypePrefix])){
            self::$langType = $langTypePrefix;
            return true;
        }
        return false;
    }

    /**
     * @param int $langKeyVal
     * @param ...$langDataList
     * @return string
     * get
     */
    public static function get(int $langKeyVal, ...$langDataList):string
    {
        return self::getByLang($langKeyVal, self::$langType, ...$langDataList);
    }

    /**
     * @param int $langKeyVal
     * @param string $langType
     * @param ...$langDataList
     * @return string
     * getByLang
     */
    public static function getByLang(int $langKeyVal, string $langType, ...$langDataList):string
    {
        $tplData    = $langDataList[0]??[];
        if(!is_array($tplData)) $tplData = [];
        return self::getTplStringByLang(LangKeyEnum::name($langKeyVal), $langType, $tplData);
    }

    /**
     * @param string $langKey
     * @param ...$langDataList
     * @return string
     * getString
     */
    public static function getString(string $langKey, ...$langDataList):string
    {
        return self::getStringByLang($langKey, self::$langType, ...$langDataList);
    }

    /**
     * @param string $langKey
     * @param string $langType
     * @param ...$langDataList
     * @return string
     * getStringByLang
     */
    public static function getStringByLang(string $langKey, string $langType, ...$langDataList):string
    {
        $tplData    = $langDataList[0]??[];
        if(!is_array($tplData)) $tplData = [];
        return self::getTplStringByLang($langKey, $langType, $tplData);
    }

    /**
     * @param string $langKey
     * @param string $langType
     * @param array $tplData
     * @return string
     * getTplStringByLang
     */
    private static function getTplStringByLang(string $langKey, string $langType, array $tplData):string
    {
        if(strlen($langKey) < 1) return '';
        $langVal        = preg_replace("/(\\\\n)+/", "\n", self::getLangVal($langKey, $langType));
        if(strlen($langVal) < 1) return '';
        $search         = [];
        $replace        = [];
        if(count($tplData) > 0) foreach ($tplData as $tplKey => $tplVal){
            $tplKeyStr      = strval($tplKey);
            if(!preg_match('/^\w+$/', $tplKeyStr)) continue;
            $tplValStr      = strval($tplVal);
            $search[]       = '"{'.$tplKeyStr.'}"';
            $replace[]      = $tplValStr;
        }
        $langText       = count($search) > 0 ? preg_replace($search, $replace, $langVal) : $langVal;
        if(!is_string($langText)) $langText = '';
        $langText           = trim($langText);
        if($langText === '-') $langText = '';
        return $langText;
    }

    /**
     * @param string $langKey
     * @param string $langType
     * @return string
     * getLangVal
     */
    private static function getLangVal(string $langKey, string $langType):string
    {
        if(!isset(self::$langData[$langType]) && !self::loadLangFile($langType)) self::$langData[$langType] = [];
        return isset(self::$langData[$langType][$langKey]) && is_string(self::$langData[$langType][$langKey]) ? self::$langData[$langType][$langKey] : (Boot::isRelease() ? '' : $langKey);
    }

    /**
     * @param string $langType
     * @return bool
     * loadLangFile
     */
    private static function loadLangFile(string $langType):bool
    {
        if(strlen($langType) < 2 || !isset(self::$langFileList[$langType])) return false;
        self::$langData[$langType]  = [];
        if(strlen(self::$langFileList[$langType]) < 1 || !file_exists(self::$langFileList[$langType])) return false;
        $fileDataList               = @file(self::$langFileList[$langType]);
        if(!is_array($fileDataList) || count($fileDataList) < 1) return false;
        $isStart                = false;
        foreach($fileDataList as $lineText){
            $lineText           = trim($lineText);
            if(!$isStart){
                if($lineText === '?>'){
                    $isStart    = true;
                    continue;
                }
                continue;
            }
            $lineTextLength     = strlen($lineText);
            if($lineTextLength < 2) continue;
            $firstCharCode      = ord(substr($lineText, 0, 1));
            if(!(($firstCharCode >= 97 && $firstCharCode <= 122) || ($firstCharCode >= 65 && $firstCharCode <= 90))) continue;
            $lineTextPos        = strpos($lineText, '=');
            if($lineTextPos < 1) continue;
            $confKey            = rtrim(substr($lineText, 0, $lineTextPos));
            if(preg_match('/^[\w\-.]+$/', $confKey)) self::$langData[$langType][$confKey] = trim(substr($lineText, $lineTextPos + 1));
        }
        return true;
    }
}